package com.zang.blogz.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zang.blogz.constant.CommentConstant;
import com.zang.blogz.entity.Comment;
import com.zang.blogz.entity.UserInfo;
import com.zang.blogz.mail.CommentEmailInfo;
import com.zang.blogz.model.output.admin.AdminCommentVO;
import com.zang.blogz.utils.BeanCopyUtils;
import com.zang.blogz.utils.LimitUtil;
import com.zang.blogz.mapper.CommentMapper;
import com.zang.blogz.model.input.ro.CommentRO;
import com.zang.blogz.model.output.CommentVO;
import com.zang.blogz.result.Result;
import com.zang.blogz.service.ArticleService;
import com.zang.blogz.service.CommentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zang.blogz.service.UserInfoService;
import io.github.vampireachao.stream.core.stream.Steam;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 朵橙i
 * @since 2022-06-17
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ArticleService articleService;

    @Autowired
    private LimitUtil limit;

    @Value("${admininfo.id}")
    private Integer adminId;

    @Override
    public List<CommentVO> getCommentByArticleId(Integer articleId) {

        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(Comment::getIsReview, CommentConstant.TRUE);

        List<Comment> list = list(queryWrapper);
        List<CommentVO> commentVOS = BeanCopyUtils.copyList(list, CommentVO.class);
        return Steam.of(commentVOS).toTree(CommentVO::getId, CommentVO::getParentId, CommentVO::setChildrenCommentVo, (a) -> {
            return a.getParentId() == -1;
        } );
    }

    /**
     * 回复评论
     *
     * @param commentRo
     * @return
     */
    @Override
    public Result<CommentRO> addComment(CommentRO commentRo) {

        if (commentRo.getArticleId() == null) {
            return Result.error("该文章不存在请刷新页面");
        }

        Integer id = (Integer) StpUtil.getExtra("id");
        commentRo.setUserId(id);

        UserInfo userInfo = userInfoService.getById(id);

        if (commentRo.getParentId() == null) {

            commentRo.setParentId(-1);
        } else {

            if (getById(commentRo.getParentId()) == null) {

                return Result.error("您想要回复的留言已删除请刷新界面");
            }
        }

        if (commentRo.getReplyUserId() == null){

            commentRo.setReplyUserId(adminId);
        }

        if (!limit.canAccess(userInfo.getNickname(), 60, 1)) {

            return Result.error("每个用户每分钟只能评论一次");
        }

        Comment comment = new Comment();
        BeanUtil.copyProperties(commentRo, comment);

        comment.setIsReview(CommentConstant.approvalFlag.get(CommentConstant.APPROVAL_STATUS));
        save(comment);

        if (CommentConstant.SEND_EMAIL){

            sendEmail(commentRo);
        }

        return Result.ok("评论成功，我们会在您收到回复的第一时间通过邮件方式告诉您", commentRo);

    }

    @Override
    public Result<String> updateApprovalFlag() {

        CommentConstant.approvalFlag.put(CommentConstant.APPROVAL_STATUS, CommentConstant.FALSE);

        return Result.ok("已开启评论审批");
    }

    @Override
    public Result<String> closureApprovalFlag() {

        CommentConstant.approvalFlag.put(CommentConstant.APPROVAL_STATUS, CommentConstant.TRUE);
        return Result.ok("已关闭评论审批");
    }

    @Override
    public Result<String> turnOnEmailNotifications() {

        CommentConstant.SEND_EMAIL = Boolean.TRUE;

        return Result.ok("已成功开启邮件通知功能");
    }

    @Override
    public Result<String> closureOnEmailNotifications() {

        CommentConstant.SEND_EMAIL = Boolean.FALSE;

        return Result.ok("已成功关闭邮件通知功能");
    }

    @Override
    public IPage<AdminCommentVO> didNotPass(Page<AdminCommentVO> page) {

        return commentMapper.didNotPass(page, CommentConstant.FALSE);

    }

    @Override
    public IPage<AdminCommentVO> pass(Page<AdminCommentVO> page) {

        return commentMapper.didNotPass(page, CommentConstant.TRUE);
    }

    @Override
    public Result<String> approved(String commentId) {

        LambdaUpdateWrapper<Comment> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.eq(Comment::getId, commentId);
        updateWrapper.set(Comment::getIsReview, CommentConstant.TRUE);

        update(updateWrapper);

        return Result.ok("已通过审批");
    }

    /**
     * 异步发送邮件通知
     *
     * @param commentRo
     */
    @Async
    public void sendEmail(CommentRO commentRo) {

        UserInfo userInfo = userInfoService.getById(commentRo.getReplyUserId());
        UserInfo receiveInfo = userInfoService.getById(commentRo.getUserId());

        CommentEmailInfo commentEmailInfo = CommentEmailInfo.builder()

                .articleName(articleService.getById(commentRo.getArticleId()).getArticleTitle())
                .sendName(userInfo.getNickname())
                .receiveName(receiveInfo.getNickname())
                .receiveEmail(receiveInfo.getEmail())
                .msg(commentRo.getCommentContent()).build();
        if (commentRo.getParentId() == -1) {

            rabbitTemplate.convertAndSend("zang-queue", commentEmailInfo);
        } else {

            rabbitTemplate.convertAndSend("zangblog-queue", commentEmailInfo);
        }
    }
}
